package com.sxf.web;

import java.util.EnumSet;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import jetbrick.template.web.servlet.JetTemplateServlet;

import org.apache.commons.lang.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
import org.springframework.web.util.IntrospectorCleanupListener;
import org.springframework.web.util.Log4jConfigListener;

import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;

import freemarker.ext.servlet.FreemarkerServlet;

@Order(3)
public class DispatcherServletInitializer extends
		AbstractDispatcherServletInitializer {
	private static ApplicationContext root;

	private static ApplicationContext web;

	public static final String SPRING_MVC_SERVLET_MAPPING = "/";

	@Override
	protected String[] getServletMappings() {
		return StringUtils.split(SPRING_MVC_SERVLET_MAPPING, ',');
	}

	@Override
	protected WebApplicationContext createRootApplicationContext() {
		XmlWebApplicationContext ctx = new XmlWebApplicationContext();
		ctx.setConfigLocations(new String[] {
				"classpath:config/spring/spring-context.xml",
				"classpath:config/spring/spring-security.xml" });
		// ctx.refresh(); //不需要refresh
		root = ctx;
		return ctx;
	}

	@Override
	protected WebApplicationContext createServletApplicationContext() {
		XmlWebApplicationContext ctx = new XmlWebApplicationContext();
		ctx.setConfigLocations(new String[] { "classpath*:config/spring/mvc/springmvc-servlet-AllInOne.xml" });
		web = ctx;
		return ctx;
	}

	@Override
	public void onStartup(ServletContext servletContext)
			throws ServletException {

		super.onStartup(servletContext);
		// Log4jConfigListener
		servletContext.setInitParameter("log4jConfigLocation",
				"classpath:log4j.properties");
		servletContext.setInitParameter("webAppRootKey", "myappfuse.root");
		servletContext.setInitParameter("log4jRefreshInterval", "60000");
		servletContext.addListener(Log4jConfigListener.class);
		// spring security session监听器
		servletContext.addListener(HttpSessionEventPublisher.class);

		// 可以提取request
		servletContext.addListener(RequestContextListener.class);
		// Spring 刷新Introspector防止内存泄露
		servletContext.addListener(IntrospectorCleanupListener.class);

		// OpenSessionInViewFilter
		// OpenSessionInViewFilter hibernateSessionInViewFilter = new
		// OpenSessionInViewFilter();
		// FilterRegistration.Dynamic filterRegistration = servletContext
		// .addFilter("hibernateFilter", hibernateSessionInViewFilter);
		// filterRegistration.addMappingForUrlPatterns(EnumSet.of(
		// DispatcherType.REQUEST, DispatcherType.FORWARD,
		// DispatcherType.INCLUDE), false, "/");

		// jpa的sessionView
		OpenEntityManagerInViewFilter entityManagerInViewFilter = new OpenEntityManagerInViewFilter();
		FilterRegistration.Dynamic filterRegistration = servletContext
				.addFilter("entityManagerInViewFilter",
						entityManagerInViewFilter);
		filterRegistration.addMappingForUrlPatterns(EnumSet.of(
				DispatcherType.REQUEST, DispatcherType.FORWARD,
				DispatcherType.INCLUDE), false, StringUtils.split(
				SPRING_MVC_SERVLET_MAPPING, ','));
		filterRegistration.setAsyncSupported(true);

		// spring security
		registerDelegate(servletContext);

		// JetTemplateServlet
		ServletRegistration.Dynamic dynamic = servletContext.addServlet(
				"jetServlet", JetTemplateServlet.class);
		dynamic.setInitParameter("jetbrick-template-config-location",
				"/WEB-INF/jetbrick-template.properties");
		dynamic.setLoadOnStartup(2);
		dynamic.addMapping("*.jetx");

		// freemarker
		FreemarkerServlet fs = new com.sxf.template.freemarker.FreemarkerServlet();
		ServletRegistration.Dynamic dynamic2 = servletContext.addServlet(
				"freemarker", fs);
		dynamic2.setInitParameter("TemplatePath", "/ftl/");
		dynamic2.setInitParameter("NoCache", "true");
		dynamic2.setInitParameter("ContentType", "text/html; charset=UTF-8");
		// 0 只对开发使用! 否则使用大一点的值.
		dynamic2.setInitParameter("template_update_delay", "0");
		// 模板文件的编码方式.
		dynamic2.setInitParameter("default_encoding", "UTF-8");
		dynamic2.setInitParameter("number_format", "0.##########");
		dynamic2.addMapping("*.ftl");

		// druid的监控
		FilterRegistration.Dynamic fr1 = servletContext.addFilter(
				"webStatFilter", WebStatFilter.class);
		fr1.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST,
				DispatcherType.FORWARD, DispatcherType.INCLUDE), false, "/*");
		fr1.setInitParameter("exclusions",
				"*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
		fr1.setAsyncSupported(true);
		// Servlet
		ServletRegistration.Dynamic druidSelvert = servletContext.addServlet(
				"DruidStatView", StatViewServlet.class);
		druidSelvert.addMapping("/druid/*");
	}

	/*
	 * 注册spring security拦截器
	 */
	private void registerDelegate(ServletContext servletContext) {
		DelegatingFilterProxy filter = new DelegatingFilterProxy();
		filter.setTargetFilterLifecycle(true);
		// org.springframework.security.FilterChainProxy
		FilterRegistration.Dynamic filterRegistration = servletContext
				.addFilter("springSecurityFilterChain", filter);
		filterRegistration.addMappingForUrlPatterns(EnumSet.of(
				DispatcherType.REQUEST, DispatcherType.FORWARD,
				DispatcherType.INCLUDE), false, StringUtils.split(
				SPRING_MVC_SERVLET_MAPPING, ','));
		filterRegistration.setAsyncSupported(true);
	}

	@Override
	protected Filter[] getServletFilters() {
		// 中文乱码处理
		CharacterEncodingFilter f = new CharacterEncodingFilter();
		f.setEncoding("UTF-8");
		f.setForceEncoding(true);
		// 浏览器不支持put,delete等method,由该filter将/blog?_method=delete转换为标准的http
		// delete方法
		HiddenHttpMethodFilter f2 = new HiddenHttpMethodFilter();
		return new Filter[] { f, f2 };
	}

	public static ApplicationContext getRoot() {
		return root;
	}

	public static ApplicationContext getWeb() {
		return web;
	}

}
